--- a/networking/ping.c
+++ b/networking/ping.c
@@ -469,6 +1053,7 @@
 	pingsock = 0,
 };
 
+static int using_dgram;
 static void
 #if ENABLE_PING6
 create_icmp_socket(len_and_sockaddr *lsa)
@@ -501,6 +1086,7 @@
 		if (sock < 0)
 #endif
 		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		using_dgram = 1;
 	}
 
 	xmove_fd(sock, pingsock);
@@ -551,10 +1137,12 @@
 				bb_perror_msg("recvfrom");
 			continue;
 		}
-		if (c >= 76) {			/* ip + icmp */
-			struct iphdr *iphdr = (struct iphdr *) G.packet;
+		if (c >= 76 || using_dgram && (c == 64)) {			/* ip + icmp */
+			if(!using_dgram) {
+				struct iphdr *iphdr = (struct iphdr *) G.packet;
 
-			pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
+				pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
+			} else pkt = (struct icmp *) G.packet;
 			if (pkt->icmp_type == ICMP_ECHOREPLY)
 				break;
 		}
@@ -946,19 +1533,21 @@
 }
 static void unpack4(char *buf, int sz, struct sockaddr_in *from)
 {
-	struct icmp *icmppkt;
 	struct iphdr *iphdr;
+	struct icmp *icmppkt;
 	int hlen;
 
 	/* discard if too short */
 	if (sz < (datalen + ICMP_MINLEN))
 		return;
+	if(!using_dgram) {
+		/* check IP header */
+		iphdr = (struct iphdr *) buf;
+		hlen = iphdr->ihl << 2;
+		sz -= hlen;
+		icmppkt = (struct icmp *) (buf + hlen);
+	} else icmppkt = (struct icmp *) buf;
 
-	/* check IP header */
-	iphdr = (struct iphdr *) buf;
-	hlen = iphdr->ihl << 2;
-	sz -= hlen;
-	icmppkt = (struct icmp *) (buf + hlen);
 	if (icmppkt->icmp_id != myid)
 		return;				/* not our ping */
 
@@ -970,7 +1559,7 @@
 			tp = (uint32_t *) icmppkt->icmp_data;
 		unpack_tail(sz, tp,
 			inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
-			recv_seq, iphdr->ttl);
+			recv_seq, using_dgram ? 42 : iphdr->ttl);
 	} else if (icmppkt->icmp_type != ICMP_ECHO) {
 		bb_error_msg("warning: got ICMP %d (%s)",
 				icmppkt->icmp_type,
@@ -1014,11 +1603,31 @@
 	int sockopt;
 
 	pingaddr.sin = lsa->u.sin;
-	if (source_lsa) {
+	if (source_lsa && !using_dgram) {
 		if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
 				&source_lsa->u.sa, source_lsa->len))
 			bb_error_msg_and_die("can't set multicast source interface");
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
+	} else if(using_dgram) {
+		struct sockaddr_in sa;
+		socklen_t sl;
+
+		sa.sin_family = AF_INET;
+		sa.sin_port = 0;
+		sa.sin_addr.s_addr = source_lsa ?
+			source_lsa->u.sin.sin_addr.s_addr : 0;
+		sl = sizeof(sa);
+
+		if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
+			perror("bind");
+			exit(2);
+		}
+
+		if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
+			perror("getsockname");
+			exit(2);
+		}
+		myid = sa.sin_port;
 	}
 
 	/* enable broadcast pings */
@@ -1035,6 +1644,15 @@
 		setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
 	}
 
+	if(using_dgram) {
+		int hold = 65536;
+		if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
+			perror("WARNING: setsockopt(IP_RECVTTL)");
+		if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
+			perror("WARNING: setsockopt(IP_RETOPTS)");
+
+	}
+
 	signal(SIGINT, print_stats_and_exit);
 
 	/* start the ping's going ... */
@@ -1069,10 +1687,33 @@
 	char control_buf[CMSG_SPACE(36)];
 
 	pingaddr.sin6 = lsa->u.sin6;
-	if (source_lsa)
+	if (source_lsa && !using_dgram)
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
+	else if(using_dgram) {
+                struct sockaddr_in6 sa = {0};
+                socklen_t sl;
 
+                sa.sin6_family = AF_INET6;
+                sa.sin6_port = 0;
+		if(source_lsa) {
+			memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr));
+		}
+                sl = sizeof(sa);
+
+                if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
+                        perror("bind");
+                        exit(2);
+                }
+
+                if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
+                        perror("getsockname");
+                        exit(2);
+                }
+                myid = sa.sin6_port;
+	}
+
 #ifdef ICMP6_FILTER
+	if(!using_dgram)
 	{
 		struct icmp6_filter filt;
 		if (!(option_mask32 & OPT_VERBOSE)) {
@@ -1198,7 +1839,7 @@
 			str_I = NULL; /* don't try to bind to device later */
 		}
 	}
-	myid = (uint16_t) getpid();
+	if(!using_dgram) myid = (uint16_t) getpid();
 	hostname = argv[optind];
 #if ENABLE_PING6
 	{
